package thesis.filesharing.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import thesis.filesharing.common.exception.system.AppSystemException;
import thesis.filesharing.dao.ExerciseDAO;
import thesis.filesharing.dao.util.EMF;
import thesis.filesharing.model.Clazz;
import thesis.filesharing.model.Exercise;
import thesis.filesharing.model.ExerciseCategory;
import thesis.filesharing.resources.Constants;
import thesis.filesharing.services.fulltextsearch.indexing.DocumentIndexing;

import com.google.appengine.api.datastore.Key;

@Repository
public class ExerciseDAOImpl implements ExerciseDAO {

	@SuppressWarnings("unchecked")
	@Override
	public Exercise saveExercise(Exercise exercise, Key classKey, List<String> tags) {
		EntityManager em = null;
		EntityTransaction transaction = null;
		try {
			em = EMF.get().createEntityManager();
			transaction = em.getTransaction();
			transaction.begin();
			
			Clazz clazz = em.find(Clazz.class, classKey);
			if (clazz != null) {
				clazz.getExercises().add(exercise);
			}
			
			em.merge(clazz);
			em.flush();
			
			String jpaql = "SELECT c FROM ExerciseCategory c WHERE c.categoryName IN (:tags)";
			Query query = em.createQuery(jpaql);
			query.setParameter("tags", tags);
			List<ExerciseCategory> categories = (List<ExerciseCategory>) query.getResultList();
			List<ExerciseCategory> tempCategories = new ArrayList<ExerciseCategory>(categories);
			for (ExerciseCategory ec : categories) {
				ec.getExerciseKeys().add(exercise.getExerciseKey());
				ec.setRanking(ec.getRanking() + 1);
				em.merge(ec);
				em.flush();
				DocumentIndexing.addEntityIndex(ec, Constants.SEARCH_INDEX_NAME);
			}
			if (categories.size() < tags.size()) {
				List<String> list = new ArrayList<String>();
				for (ExerciseCategory e : categories) {
					list.add(e.getCategoryName());
				}
				for (String t : tags) {
					// Create new tag if there is no such tag name
					ExerciseCategory c = null;
					if (!list.contains(t)) {
						c = new ExerciseCategory(t, 1L);
						c.getExerciseKeys().add(exercise.getExerciseKey());
						em.persist(c);
						em.flush();
						tempCategories.add(c);
						DocumentIndexing.addEntityIndex(c, Constants.SEARCH_INDEX_NAME);
					}
				}
			}
			for (ExerciseCategory ec : tempCategories) {
				exercise.getExerciseCategoryKeys().add(ec.getCategoryKey());
			}
			em.merge(exercise);
			em.flush();
			
			transaction.commit();
			return exercise;
		} catch (Exception ex) {
			if (transaction != null && transaction.isActive()) {
				transaction.rollback();
			}
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public Exercise findExerciseById(Key exerciseKey) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			return em.find(Exercise.class, exerciseKey);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Exercise> listExercisesOfClass(Key classKey, String exerciseType) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			Clazz c = em.find(Clazz.class, classKey);
			if (c != null) {
				String jpaql = "SELECT e FROM Exercise e WHERE e.clazz = :clazz AND e.exerciseType = :exerciseType ORDER BY e.demandDate DESC";
				Query query = em.createQuery(jpaql);
				query.setParameter("clazz", c);
				query.setParameter("exerciseType", exerciseType);
				return (List<Exercise>) query.getResultList();
			}
			return null;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}
}
